#pragma once

using namespace std;
#include <vector>
#include <complex>
#include <fftw3.h>
#include <CUtil.h>
#include <vector>

class CGraph {
 public:
  vector<double> Val;
  vector<double> Index;
  vector<double> IndexScaled;
  CGraph* chisq;
  
  double mean, std;

  const static double NONE = -1E10;

  vector<complex<double> > ValFFT;

  int Bins;

  CGraph() {
  }

  void Copy(const CGraph& copy) {
   Initialize(copy.Bins);
   for (int i=0;i<Bins;i++) {
     Val[i] = copy.Val[i];
     Index[i] = copy.Index[i];
     IndexScaled[i] = copy.IndexScaled[i];
   }
 }

 ~CGraph() {
   Delete();
  }

  void Delete() {
  }


  double& operator[](int i) {
    return Val[i];
  }

  void Initialize(int bins) {
    Delete();
    Bins = bins;
    Val.resize(bins);
    Index.resize(bins);
    IndexScaled.resize(bins);
    ValFFT.resize(bins);
    


    for (int i=0;i<bins;i++) {
      Val[i] = 0.0;
      Index[i] = i;
      IndexScaled[i] = i;
      ValFFT[i] = 0.0;
    }

  }


  void Mul(CGraph& o) {
    for (int i=0;i<Bins;i++) {
      Val[i] *= o.Val[i];
    }
  }

  void MulFFT(CGraph& o) {
    for (int i=0;i<Bins;i++) {
      ValFFT[i] *= o.ValFFT[i];
    }
  }


  void Gaussian(double B);
  void Smooth(double B);


  void LikelihoodFromChisq() {
    // find min
    double m = 1E20;
    for (int i=0;i<Bins;i++)
      m = min(Val[i], m);

    for (int i=0;i<Bins;i++) {
      Val[i] = exp(-(Val[i]-m));
    }
  }


  void calculateStatistics();

  void cutModes(int from, int to);

  static double ChiSQ(CGraph& temp, CGraph& two);


  void scaleX(double);

  void FFT();
  void FFTInv();

  void SaveBin(string Filename);
  void LoadBin(string Filename);

  void LoadText(string Filename);
  void SaveText(string Filename);

  void Mean();
  void Std();

  void Scale(double v);

  void dampNoise(double A, double B);

  void SaveTextFFT(string Filename);

  void RenderGauss(double position, double sigma, double amp);


  float getValAtScaledIndex(double& index);

  int getIndexAtScaledIndex(double& index);

  void MulWithIndex(CGraph& o);

};
